(* coversion de couleur rgb ver le format opengl*)
let glColor_of_color (r,g,b) = ((float_of_int r) /. 255., 
                                (float_of_int g) /. 255., 
                                (float_of_int b) /. 255.)
(** get an GLArea
 @attach  widget mother add function
 @width widht of the area
 @height height of the area
 *)
let getGlArea attach width height = 
    let area = GlGtk.area [`DEPTH_SIZE 1; `RGBA; `DOUBLEBUFFER]
      ~width: width ~height: height
            ~packing: attach () in
    area#event#add[`BUTTON_RELEASE;
                   `BUTTON_PRESS;
                   `KEY_PRESS;
                   `POINTER_MOTION;
                   `POINTER_MOTION_HINT
                   ];
    area
                                                                     
class virtual render ()=
object
    method virtual draw :bool -> unit
end
    
class view area = 
object (self)
  val mutable fil_de_fer = false
  val mutable hold = false
  val mutable curPosX = 0.0
  val mutable curPosY = 0.0
  val mutable renderList: render list = []
  val mutable view_transx = 0.0
  val mutable view_transy = 0.0
  val mutable view_transz = -50.0

  method transx a = view_transx <- a
  method transy a = view_transy <- a
  method transz a = view_transz <- a
  
  val mutable view_rotx = 0.0
  val mutable view_roty = 0.0
  val mutable view_rotz = 0.0

  method rotx a = view_rotx <- a
  method roty a = view_roty <- a
  method rotz a = view_rotz <- a

  method add o = renderList <- o::renderList
  
  method draw () =
    GlClear.clear [`color;`depth];

    GlMat.push ();
    
    GlMat.rotate ~angle:view_rotx ~x:1.0 ();
    GlMat.rotate ~angle:view_roty ~y:1.0 ();
    GlMat.rotate ~angle:view_rotz ~z:1.0 ();
    
    List.iter (fun o -> o#draw (fil_de_fer)) renderList;
    GlMat.pop ();

    Gl.flush ();
    area#swap_buffers ()

  method idle () =
    if area#misc#visible then self#draw ();
    true


  method reshape ~width:w ~height:h =
    GlDraw.viewport ~x:0 ~y:0 ~w ~h;
    GlMat.mode `projection;
    GlMat.load_identity ();
    let r = float w /. float h in
    let r' = 1. /. r in
    if (w>h) then
      GlMat.frustum ~x:(-.r,r) ~y:(-1.0,1.0) ~z:(5.0,60.0)
    else
      GlMat.frustum ~x:(-1.0,1.0) ~y:(-.r',r') ~z:(5.0,60.0);

    GlMat.mode `modelview;
    GlMat.load_identity();
    GlMat.translate ~z:(-50.0) ();
    GlClear.clear[`color;`depth]

  method init () =
    let pos = -50.0, -50.0, 0.0, 0.0 in
    GlLight.light ~num:1 (`position pos);
    List.iter Gl.enable
      [`cull_face;`depth_test;`normalize];
    
  method onButtonPressed event = 
      if GdkEvent.Button.button event = 1 then
              hold <- true;
              curPosX <- GdkEvent.Button.x event;
              curPosY <- GdkEvent.Button.y event;
      true
  method onButtonReleased event = 
      if GdkEvent.Button.button event = 1 then hold <- false;
      true
  
  method onScroll event =
    if (GdkEvent.Scroll.direction event = `DOWN)
    then GlMat.translate ~z:(-0.5) ()
    else GlMat.translate ~z:(+0.5) ();
    true
    
  method onMouseMove event =
      if(hold) then
          begin
    let (x, y) = (GdkEvent.Motion.x event,GdkEvent.Motion.y event)
    in
     let state = GdkEvent.Motion.state event in
       if Gdk.Convert.test_modifier `BUTTON1 state then
           view_rotz <- view_rotz +. x -. curPosX;
           view_rotx <- view_rotx +. curPosY -.y;
           curPosX <- x;
           curPosY <- y;
           true
        end
       else
           false
           
    (*method onKeyPressed event =
        let key = GdkEvent.Key.keyval event in
        if key = GdkKeysyms._Left  then  GlMat.translate ~x:(-0.0) ();
        if key = GdkKeysyms._Right then  GlMat.translate ~x:(-0.0) ();
        if key = GdkKeysyms._Up    then  GlMat.translate ~y:(-0.0) ();
        if key = GdkKeysyms._Down  then  GlMat.translate ~y:(-0.0) (); 
        if key = GdkKeysyms._Escape then fil_de_fer <- not fil_de_fer;
        true
*)
  initializer
    area#connect#realize ~callback: self#init;
    area#connect#display ~callback: self#draw;
    area#connect#reshape ~callback: self#reshape;
    area#event#connect#button_press ~callback: self#onButtonPressed;
    area#event#connect#button_release ~callback: self#onButtonReleased;
    area#event#connect#scroll ~callback: self#onScroll;
    area#event#connect#motion_notify ~callback: self#onMouseMove;
    ()
end

